# -*-coding:utf-8-*-
import numpy as np

a: np.ndarray = np.arange(6).reshape(2, 3)
b = np.array(a)
c = np.array([])

# 迭代器对象np.nditer,注意迭代出的是单个元素的0维ndarray
for i in np.nditer(a):
    print(i, end=' ')  # 0 1 2 3 4 5,type(i)=ndarray
print()
for i in np.nditer(a, order='F'):
    print(i, end=' ')  # 0 3 1 4 2 5,按列顺序迭代
print()
# flags参数为external_loop时，根据order参数迭代出的是每行或每列的数组
for i in np.nditer(a, order='F', flags=['external_loop']):
    print(i, end=' ')  # [0 3] [1 4] [2 5]
print()
print(list(np.nditer(a)))  # [array(0), array(1), array(2), array(3), array(4), array(5)]
print(list(int(i) for i in np.nditer(a)))  # [0, 1, 2, 3, 4, 5]

# np.nditer修改数组,op_flags值为readonly、readwrite或writeonly。并不推荐这种方法来修改数组值，可以作为参考
for x in np.nditer(b, op_flags=['writeonly']):
    x[...] = 2*x

# np.nditer广播迭代，如果两个数组(其中一个可以为单个数值)是可广播的，nditer组合对象能够同时迭代它们
for x, y in np.nditer([a, 2]):
    print(x, y, end=',')  # 0 2,1 2,2 2,3 2,4 2,5 2
print()

# 一维迭代器ndarray.flat。flat属性是一个可赋值的属性，对flat属性赋值将导致整个数组的元素都被覆盖
# 和一维副本ndarray.flatten、一维视图ndarray.ravel的不同点：
# 1.flatten是请求分配内存来保存副本，ravel和flat不会，所以改变flatten的元素不会对原数组有影响
# 2.flatten和ravel返回ndarray，flat返回iter
flat = a.flat
for i in flat:
    print(i, end=' ')  # 0 1 2 3 4 5,type(i)=int32
print()
print(flat[[1, 2]], flat[0])  # [1 2] 0,可以通过索引访问元素
a.flat = 1  # 对flat赋值，a将变成[[1 1 1] [1 1 1]]
a.flatten()[5] = 1  # a:[[0 1 2] [3 4 5]],flatten返回副本，a不变
a.ravel()[5] = 1  # a:[[0 1 2] [3 4 1]],ravel返回视图，a改变

# 直接迭代
for row in a:
    for item in row:
        print(item, end=' ')
    print()
